import { NativeEventEmitter, NativeModules, Platform, PermissionsAndroid, Permission } from 'react-native';
import { PermissionCheckResult, PermissionRequestOptions, PermanentlyDeniedPermissions } from './types';
import { DlnaError, DlnaErrorCode } from './errors';

// 创建权限事件发射器
const DlnaPlayerModule = NativeModules.DlnaPlayer || {};
export const permissionEventEmitter = new NativeEventEmitter(DlnaPlayerModule);

/**
 * 权限类型
 */
export enum PermissionType {
  /**
   * 本地网络权限
   */
  LOCAL_NETWORK = 'LOCAL_NETWORK',
  
  /**
   * 互联网权限
   */
  INTERNET = 'INTERNET',
  
  /**
   * 网络状态权限
   */
  NETWORK_STATE = 'NETWORK_STATE',
  
  /**
   * WiFi状态权限
   */
  WIFI_STATE = 'WIFI_STATE',
  
  /**
   * WiFi多播权限
   */
  WIFI_MULTICAST = 'WIFI_MULTICAST'
}

/**
 * 权限状态
 */
export enum PermissionStatus {
  /**
   * 已授予
   */
  GRANTED = 'GRANTED',
  
  /**
   * 已拒绝
   */
  DENIED = 'DENIED',
  
  /**
   * 未确定
   */
  UNDETERMINED = 'UNDETERMINED',
  
  /**
   * 受限制的（仅iOS）
   */
  RESTRICTED = 'RESTRICTED',
  
  /**
   * 永久拒绝（用户选择"不再询问"）
   */
  PERMANENTLY_DENIED = 'PERMANENTLY_DENIED'
}

/**
 * 权限事件类型
 */
export enum PermissionEventType {
  /**
   * 权限状态变更
   */
  PERMISSION_STATUS_CHANGED = 'permissionStatusChanged'
}

/**
 * 权限状态变更事件数据
 */
export interface PermissionStatusEventData {
  /**
   * 权限类型
   */
  permissionType: PermissionType;
  
  /**
   * 权限状态
   */
  status: PermissionStatus;
}

/**
 * 权限信息，包含权限说明
 */
export interface PermissionInfo {
  /**
   * 权限类型
   */
  type: PermissionType;
  
  /**
   * 权限名称
   */
  name: string;
  
  /**
   * 权限说明
   */
  description: string;
  
  /**
   * 对应的Android权限标识
   */
  androidPermission?: Permission;
  
  /**
   * 请求理由（用于向用户解释为什么需要该权限）
   */
  rationale: string;
  
  /**
   * 权限是否是必需的
   */
  isRequired: boolean;
}

/**
 * DLNA播放器所需的权限列表
 */
export const PERMISSIONS: PermissionInfo[] = [
  {
    type: PermissionType.INTERNET,
    name: '网络访问',
    description: '允许应用程序连接到互联网',
    androidPermission: PermissionsAndroid.PERMISSIONS.INTERNET,
    rationale: 'DLNA播放器需要访问网络以发现设备并传输媒体内容。',
    isRequired: true
  },
  {
    type: PermissionType.NETWORK_STATE,
    name: '网络状态',
    description: '允许应用程序访问有关网络的信息',
    androidPermission: PermissionsAndroid.PERMISSIONS.ACCESS_NETWORK_STATE,
    rationale: 'DLNA播放器需要检测当前的网络连接状态以确保设备可以正常通信。',
    isRequired: true
  },
  {
    type: PermissionType.WIFI_STATE,
    name: 'WiFi状态',
    description: '允许应用程序访问有关WiFi网络的信息',
    androidPermission: PermissionsAndroid.PERMISSIONS.ACCESS_WIFI_STATE,
    rationale: 'DLNA播放器需要检测WiFi网络状态以确保设备在同一网络中。',
    isRequired: true
  },
  {
    type: PermissionType.WIFI_MULTICAST,
    name: 'WiFi多播',
    description: '允许应用程序接收所有多播包',
    androidPermission: PermissionsAndroid.PERMISSIONS.CHANGE_WIFI_MULTICAST_STATE,
    rationale: 'DLNA设备发现需要使用多播协议，这是发现本地网络上的设备所必需的。',
    isRequired: true
  },
  {
    type: PermissionType.LOCAL_NETWORK,
    name: '本地网络',
    description: '允许应用程序访问本地网络上的设备',
    rationale: 'DLNA播放器需要访问本地网络以发现和连接到DLNA设备。',
    isRequired: true
  }
];

// 缓存权限状态
const permissionStatusCache = new Map<PermissionType, PermissionStatus>();

// 权限请求时间跟踪，用于避免频繁请求
const lastPermissionRequests = new Map<PermissionType, number>();

// 权限请求频率限制（毫秒）
const PERMISSION_REQUEST_COOLDOWN = 3000; // 3秒

/**
 * 获取Android平台所需的权限列表
 * @returns 权限列表
 */
export function getAndroidPermissions(): Permission[] {
  return PERMISSIONS
    .filter(p => p.androidPermission !== undefined)
    .map(p => p.androidPermission as Permission);
}

/**
 * 检查iOS平台权限
 * 注意：iOS大多数权限是由系统自动处理的，但本地网络权限需要在Info.plist中配置
 * @returns Promise<Map<PermissionType, PermissionStatus>> 权限状态映射
 */
async function checkIOSPermissions(): Promise<Map<PermissionType, PermissionStatus>> {
  const permissionStatusMap = new Map<PermissionType, PermissionStatus>();
  
  // 如果原生模块实现了checkLocalNetworkPermission方法，则调用它
  if (DlnaPlayerModule.checkLocalNetworkPermission) {
    try {
      const hasLocalNetworkPermission = await DlnaPlayerModule.checkLocalNetworkPermission();
      permissionStatusMap.set(
        PermissionType.LOCAL_NETWORK, 
        hasLocalNetworkPermission ? PermissionStatus.GRANTED : PermissionStatus.DENIED
      );
    } catch (error) {
      console.warn('检查本地网络权限失败:', error);
      permissionStatusMap.set(PermissionType.LOCAL_NETWORK, PermissionStatus.UNDETERMINED);
    }
  } else {
    // 无法确定权限状态，假设为已授予（iOS中，本地网络权限通常在Info.plist中配置）
    permissionStatusMap.set(PermissionType.LOCAL_NETWORK, PermissionStatus.GRANTED);
  }
  
  // 其他权限在iOS上通常是自动授予的，或者通过Info.plist配置
  permissionStatusMap.set(PermissionType.INTERNET, PermissionStatus.GRANTED);
  permissionStatusMap.set(PermissionType.NETWORK_STATE, PermissionStatus.GRANTED);
  permissionStatusMap.set(PermissionType.WIFI_STATE, PermissionStatus.GRANTED);
  permissionStatusMap.set(PermissionType.WIFI_MULTICAST, PermissionStatus.GRANTED);
  
  return permissionStatusMap;
}

/**
 * 检查Android平台权限
 * @returns Promise<Map<PermissionType, PermissionStatus>> 权限状态映射
 */
async function checkAndroidPermissions(): Promise<Map<PermissionType, PermissionStatus>> {
  const permissionStatusMap = new Map<PermissionType, PermissionStatus>();
  
  for (const permInfo of PERMISSIONS) {
    if (permInfo.androidPermission) {
      try {
        const granted = await PermissionsAndroid.check(permInfo.androidPermission);
        permissionStatusMap.set(
          permInfo.type,
          granted ? PermissionStatus.GRANTED : PermissionStatus.DENIED
        );
      } catch (error) {
        console.warn(`检查权限 ${permInfo.name} 失败:`, error);
        permissionStatusMap.set(permInfo.type, PermissionStatus.UNDETERMINED);
      }
    }
  }
  
  return permissionStatusMap;
}

/**
 * 检查Android平台是否有永久拒绝的权限
 * @param permissionsToRequest 要检查的权限列表
 * @returns Promise<PermanentlyDeniedPermissions> 永久拒绝的权限信息
 */
async function checkPermanentlyDeniedPermissions(
  permissionsToRequest: PermissionInfo[]
): Promise<PermanentlyDeniedPermissions> {
  const permanentlyDeniedPermissions: string[] = [];
  
  if (Platform.OS !== 'android') {
    return {
      hasPermanentlyDeniedPermissions: false
    };
  }
  
  // 检测权限是否被永久拒绝
  for (const permInfo of permissionsToRequest) {
    if (permInfo.androidPermission) {
      try {
        const granted = await PermissionsAndroid.check(permInfo.androidPermission);
        if (!granted) {
          // 权限未授予，检查用户是否勾选了"不再询问"
          const canAsk = await PermissionsAndroid.request(
            permInfo.androidPermission,
            {
              title: '权限检查',
              message: permInfo.rationale,
              buttonPositive: '确定'
            }
          ) !== PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN;
          
          if (!canAsk) {
            permanentlyDeniedPermissions.push(permInfo.name);
            // 更新权限状态缓存
            permissionStatusCache.set(permInfo.type, PermissionStatus.PERMANENTLY_DENIED);
          }
        }
      } catch (error) {
        console.warn(`检查权限永久拒绝状态失败 ${permInfo.name}:`, error);
      }
    }
  }
  
  return {
    hasPermanentlyDeniedPermissions: permanentlyDeniedPermissions.length > 0,
    permanentlyDeniedPermissions: permanentlyDeniedPermissions.length > 0 ? permanentlyDeniedPermissions : undefined
  };
}

/**
 * 请求Android平台权限
 * @param permissionsToRequest 需要请求的权限信息列表
 * @param options 权限请求选项
 * @returns Promise<Map<PermissionType, PermissionStatus>> 权限状态映射
 */
async function requestAndroidPermissions(
  permissionsToRequest: PermissionInfo[],
  options?: PermissionRequestOptions
): Promise<Map<PermissionType, PermissionStatus>> {
  const permissionStatusMap = new Map<PermissionType, PermissionStatus>();
  
  // 构建权限请求映射
  const permissionsMap: { [key: string]: Permission } = {};
  const rationaleMap: { [key: string]: string } = {};
  
  for (const permInfo of permissionsToRequest) {
    if (permInfo.androidPermission) {
      permissionsMap[permInfo.type] = permInfo.androidPermission;
      rationaleMap[permInfo.type] = permInfo.rationale;
    }
  }
  
  const permissionsToAsk = Object.values(permissionsMap);
  if (permissionsToAsk.length === 0) {
    return permissionStatusMap;
  }
  
  // 检查是否有权限被永久拒绝
  const permanentlyDeniedStatus = await checkPermanentlyDeniedPermissions(permissionsToRequest);
  if (permanentlyDeniedStatus.hasPermanentlyDeniedPermissions) {
    // 如果提供了永久拒绝回调，则调用它
    if (options?.onPermanentlyDenied) {
      options.onPermanentlyDenied();
    }
    
    // 更新状态映射
    for (const permInfo of permissionsToRequest) {
      if (permanentlyDeniedStatus.permanentlyDeniedPermissions?.includes(permInfo.name)) {
        permissionStatusMap.set(permInfo.type, PermissionStatus.PERMANENTLY_DENIED);
      }
    }
    
    // 对于永久拒绝的权限，抛出特殊错误
    if (permanentlyDeniedStatus.permanentlyDeniedPermissions?.length === permissionsToRequest.length) {
      throw new DlnaError(
        DlnaErrorCode.PERMISSION_PERMANENTLY_DENIED,
        '权限已被永久拒绝，请在系统设置中手动授予权限',
        {
          permissions: permanentlyDeniedStatus.permanentlyDeniedPermissions
        }
      );
    }
  }
  
  // 请求多个权限
  try {
    const results = await PermissionsAndroid.requestMultiple(permissionsToAsk);
    
    // 处理结果
    for (const [permType, permission] of Object.entries(permissionsMap)) {
      // 如果已经是永久拒绝状态，跳过
      if (permissionStatusMap.get(permType as PermissionType) === PermissionStatus.PERMANENTLY_DENIED) {
        continue;
      }
      
      let status: PermissionStatus;
      if (results[permission] === PermissionsAndroid.RESULTS.GRANTED) {
        status = PermissionStatus.GRANTED;
      } else if (results[permission] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
        status = PermissionStatus.PERMANENTLY_DENIED;
      } else {
        status = PermissionStatus.DENIED;
      }
      
      permissionStatusMap.set(permType as PermissionType, status);
      
      // 发送权限状态变更事件
      permissionEventEmitter.emit(PermissionEventType.PERMISSION_STATUS_CHANGED, {
        permissionType: permType,
        status
      });
      
      // 更新缓存
      permissionStatusCache.set(permType as PermissionType, status);
      
      // 更新请求时间
      lastPermissionRequests.set(permType as PermissionType, Date.now());
    }
  } catch (error) {
    console.error('请求权限失败:', error);
    throw new DlnaError(
      DlnaErrorCode.PERMISSION_ERROR,
      '请求权限失败',
      error
    );
  }
  
  return permissionStatusMap;
}

/**
 * 获取所有权限的状态
 * @returns Promise<Map<PermissionType, PermissionStatus>> 权限状态映射
 */
export async function getPermissionStatus(): Promise<Map<PermissionType, PermissionStatus>> {
  if (Platform.OS === 'ios') {
    const statusMap = await checkIOSPermissions();
    
    // 更新缓存
    for (const [permType, status] of statusMap.entries()) {
      permissionStatusCache.set(permType, status);
    }
    
    return statusMap;
  } else if (Platform.OS === 'android') {
    const statusMap = await checkAndroidPermissions();
    
    // 更新缓存
    for (const [permType, status] of statusMap.entries()) {
      permissionStatusCache.set(permType, status);
    }
    
    return statusMap;
  }
  
  // 其他平台默认返回空映射
  return new Map();
}

/**
 * 检查权限状态
 * @returns Promise<PermissionCheckResult> 权限检查结果
 */
export async function checkPermissions(): Promise<PermissionCheckResult> {
  try {
    // 如果原生模块提供了权限检查方法，优先使用
    if (DlnaPlayerModule.checkPermissions) {
      return await DlnaPlayerModule.checkPermissions();
    }
    
    const permissionStatusMap = await getPermissionStatus();
    const missingPermissions: string[] = [];
    
    // 检查必需的权限
    for (const permInfo of PERMISSIONS) {
      if (permInfo.isRequired) {
        const status = permissionStatusMap.get(permInfo.type);
        if (status !== PermissionStatus.GRANTED) {
          missingPermissions.push(permInfo.name);
        }
      }
    }
    
    return {
      hasPermissions: missingPermissions.length === 0,
      missingPermissions: missingPermissions.length > 0 ? missingPermissions : undefined
    };
  } catch (error) {
    console.error('检查权限失败:', error);
    const errorMessage = error instanceof Error ? error.message : String(error);
    
    return {
      hasPermissions: false,
      errorMessage: '权限检查失败: ' + errorMessage
    };
  }
}

/**
 * 请求所需权限
 * @param options 权限请求选项
 * @returns Promise<boolean> 是否获得所有必需权限
 */
export async function requestPermissions(options?: PermissionRequestOptions): Promise<boolean> {
  try {
    const showRationale = options?.showRationale !== false; // 默认为true
    const forceRequest = options?.forceRequest === true; // 默认为false
    
    // iOS权限通常由系统自动处理，无需手动请求
    if (Platform.OS === 'ios') {
      // 对于iOS，展示一个引导提示，说明如何在系统设置中启用本地网络权限
      if (DlnaPlayerModule.promptForLocalNetworkPermission) {
        await DlnaPlayerModule.promptForLocalNetworkPermission({
          title: options?.title,
          message: options?.message
        });
      }
      
      const result = await checkPermissions();
      return result.hasPermissions;
    }
    
    // Android权限需要动态请求
    if (Platform.OS === 'android') {
      // 获取当前权限状态
      const currentStatusMap = await getPermissionStatus();
      const permissionsToRequest: PermissionInfo[] = [];
      
      // 过滤出需要请求的权限
      for (const permInfo of PERMISSIONS) {
        if (permInfo.androidPermission && 
            currentStatusMap.get(permInfo.type) !== PermissionStatus.GRANTED) {
          // 检查是否在冷却期内（最近已请求过）
          const lastRequestTime = lastPermissionRequests.get(permInfo.type) || 0;
          const timeSinceLastRequest = Date.now() - lastRequestTime;
          
          // 如果不是强制请求且在冷却期内，则跳过
          if (!forceRequest && timeSinceLastRequest < PERMISSION_REQUEST_COOLDOWN) {
            console.log(`跳过权限 ${permInfo.name} 请求，因为最近已请求过 (${timeSinceLastRequest}ms前)`);
            continue;
          }
          
          // 如果权限已被永久拒绝且不是强制请求，跳过
          if (!forceRequest && currentStatusMap.get(permInfo.type) === PermissionStatus.PERMANENTLY_DENIED) {
            console.log(`跳过权限 ${permInfo.name} 请求，因为用户已永久拒绝`);
            continue;
          }
          
          permissionsToRequest.push(permInfo);
        }
      }
      
      // 如果已经拥有所有权限
      if (permissionsToRequest.length === 0) {
        return true;
      }
      
      // 如果需要显示请求理由，先显示给用户
      if (showRationale) {
        for (const permInfo of permissionsToRequest) {
          // React Native 的权限API限制，我们使用最佳方法来处理权限说明
          try {
            if (permInfo.androidPermission && DlnaPlayerModule.showPermissionRationale) {
              // 如果原生模块实现了显示权限理由的方法，则调用它
              await DlnaPlayerModule.showPermissionRationale(
                permInfo.name,
                permInfo.rationale
              );
            }
          } catch (e) {
            // 如果原生方法失败，忽略错误，继续请求权限
            console.warn(`无法显示权限理由 ${permInfo.name}:`, e);
          }
        }
      }
      
      // 请求权限
      const resultMap = await requestAndroidPermissions(permissionsToRequest, options);
      
      // 检查是否所有必需的权限都被授予
      const deniedPermissions: string[] = [];
      const permanentlyDeniedPermissions: string[] = [];
      
      for (const permInfo of permissionsToRequest) {
        if (permInfo.isRequired) {
          const status = resultMap.get(permInfo.type);
          if (status === PermissionStatus.PERMANENTLY_DENIED) {
            permanentlyDeniedPermissions.push(permInfo.name);
          } else if (status !== PermissionStatus.GRANTED) {
            deniedPermissions.push(permInfo.name);
          }
        }
      }
      
      // 如果有永久拒绝的权限，调用回调
      if (permanentlyDeniedPermissions.length > 0 && options?.onPermanentlyDenied) {
        options.onPermanentlyDenied();
      }
      
      // 如果有普通拒绝的权限，调用回调
      if (deniedPermissions.length > 0 && options?.onDenied) {
        options.onDenied();
      }
      
      // 如果有任何必需的权限被拒绝
      if (deniedPermissions.length > 0 || permanentlyDeniedPermissions.length > 0) {
        if (permanentlyDeniedPermissions.length > 0) {
          throw new DlnaError(
            DlnaErrorCode.PERMISSION_PERMANENTLY_DENIED,
            '部分权限已被永久拒绝，请在系统设置中手动授予权限',
            {
              deniedPermissions,
              permanentlyDeniedPermissions
            }
          );
        } else {
          throw DlnaError.permissionError(
            deniedPermissions,
            '未获得所需的权限，DLNA功能可能无法正常工作'
          );
        }
      }
      
      return true;
    }
    
    return false;
  } catch (error) {
    if (error instanceof DlnaError) {
      throw error;
    }
    
    console.error('请求权限失败:', error);
    const errorMessage = error instanceof Error ? error.message : String(error);
    throw new DlnaError(
      DlnaErrorCode.PERMISSION_ERROR,
      '请求权限失败: ' + errorMessage,
      error
    );
  }
}

/**
 * 检查单个权限状态
 * @param permissionType 权限类型
 * @returns Promise<PermissionStatus> 权限状态
 */
export async function checkSinglePermission(permissionType: PermissionType): Promise<PermissionStatus> {
  // 如果缓存中有，直接返回
  if (permissionStatusCache.has(permissionType)) {
    return permissionStatusCache.get(permissionType) as PermissionStatus;
  }
  
  const statusMap = await getPermissionStatus();
  return statusMap.get(permissionType) || PermissionStatus.UNDETERMINED;
}

/**
 * 添加权限状态变更监听器
 * @param listener 监听器函数
 * @returns 事件订阅对象
 */
export function addPermissionStatusChangeListener(
  listener: (event: PermissionStatusEventData) => void
) {
  return permissionEventEmitter.addListener(
    PermissionEventType.PERMISSION_STATUS_CHANGED,
    listener
  );
}

/**
 * 移除权限状态变更监听器
 * @param subscription 事件订阅对象
 */
export function removePermissionStatusChangeListener(
  subscription: any
): void {
  if (subscription && typeof subscription.remove === 'function') {
    subscription.remove();
  }
}

/**
 * 获取权限信息
 * @param permissionType 权限类型
 * @returns PermissionInfo | undefined 权限信息
 */
export function getPermissionInfo(permissionType: PermissionType): PermissionInfo | undefined {
  return PERMISSIONS.find(p => p.type === permissionType);
}

/**
 * 获取所需的权限信息列表
 * @returns PermissionInfo[] 权限信息列表
 */
export function getRequiredPermissions(): PermissionInfo[] {
  return PERMISSIONS.filter(p => p.isRequired);
}

/**
 * 检测是否有永久拒绝的权限
 * @returns Promise<PermanentlyDeniedPermissions> 永久拒绝的权限信息
 */
export async function checkPermanentlyDeniedPermissionsStatus(): Promise<PermanentlyDeniedPermissions> {
  const permissionsToCheck = getRequiredPermissions();
  return checkPermanentlyDeniedPermissions(permissionsToCheck);
}

/**
 * 重置权限请求记录
 * 用于测试或手动强制请求权限
 */
export function resetPermissionRequestHistory(): void {
  lastPermissionRequests.clear();
} 